
#pragma once
#include<iostream>
#include<string>
#include<jsoncpp/json/json.h>
#include<memory>

static const std::string sep = "\r\n";

// 设计一下协议的报头和报文的完整格式
// "len"\r\n"{json}"\r\n --- 完整的报文， len 有效载荷的长度！
// \r\n: 区分len 和 json 串
// \r\n: 暂是没有其他用，打印方便，debug
// 添加报头
std::string Encode(const std::string &jsonstr)
{
    int len = jsonstr.size();
    std::string lenstr = std::to_string(len);
    return lenstr + sep + jsonstr + sep;
}
//"len"\r\n"{json}"\r\n
//"len"\r\n"{js
//"len"
//"len"\r\n"{json}"\r\n"le
//"len"\r\n"{json}"\r\n"len"\r\n"{json}"\r\n"len"\r\n"{json}"\r\n
std::string Decode(std::string &packagesteam)
{
    auto pos = packagesteam.find(sep);
    if(pos == std::string::npos)    return std::string();

    std::string lenstr = packagesteam.substr(0, pos);   //[0 , pos)
    int len = std::stoi(lenstr);
    //计算一个完整报文应该多长
    int total = lenstr.size() + len + 2 * sep.size();
    if(packagesteam.size() < total) return std::string();
    
    std::string jsonstr = packagesteam.substr(pos + sep.size(), len);

    packagesteam.erase(0, total); //不能const
    return jsonstr;
}

class Request
{
public:

    Request()
    {}
    Request(int x, int y, char oper)
        :_x(x)
        ,_y(y)
        ,_oper(oper)
    {}
    bool Serialize(std::string *out)  // 序列化  : 结构化字段-->字符串
    {
        Json::Value root;
        root["x"] = _x;
        root["y"] = _y;
        root["oper"] = _oper;

        // Json::Value sub;
        // sub["name"] = "zhangsan";
        // sub["age"] = root;
        //Json::FastWriter write;
        //root.append(sub);

        Json::StyledWriter write;
        std::string s = write.write(root);     //传入json对象

        *out = s;
        return true;
    }
    bool Deserialize(std::string &in) //反序列化:  字符串-->结构化字段
    {
        Json::Value root;
        Json::Reader reader;
        bool res = reader.parse(in, root);
        if(!res) return false;

        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _oper = root["oper"].asInt();

        return true;
    }
    void Print()
    {
        std::cout << _x << std::endl;
        std::cout << _y << std::endl;
        std::cout << _oper << std::endl;
    }

    ~Request()
    {}
    int X()
    {
        return _x;
    }
    int Y()
    {
        return _y;
    }
    char Oper()
    {
        return _oper;
    }
    void SetValue(int x, int y, char oper)
    {
        _x = x;
        _y = y;
        _oper = oper;
    }

private:
    int _x;
    int _y;
    char _oper;  // + - * /
};

// 
class Response
{
public:
    Response() : _result(0), _code(0), _desc("success")
    {}
    bool Serialize(std::string *out)  // 序列化  : 结构化字段-->字符串
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        root["desc"] = _desc;

        // Json::Value sub;
        // sub["name"] = "zhangsan";
        // sub["age"] = root;
        //Json::FastWriter write;
        //root.append(sub);

        Json::StyledWriter write;
        std::string s = write.write(root);     //传入json对象

        *out = s;
        return true;
    }
    bool Deserialize(std::string &in) //反序列化:  字符串-->结构化字段
    {
        Json::Value root;
        Json::Reader reader;
        bool res = reader.parse(in, root);
        if(!res) return false;
        _result = root["result"].asInt();
        _code = root["code"].asInt();
        _desc = root["desc"].asString();

        return true;
    }
    void PrintResult()
    {
        std::cout << "result: " << _result << ", code: " << _code << ", desc: " << _desc << std::endl; 
    }
    ~Response()
    {}

public:
    int _result;
    int _code;  // 0:sucess  1:div zero  2.非法操作
    std::string _desc; //状态码
};

class Factory
{
public:
    static std::shared_ptr<Request> BuildRequestDefault()
    {
        return std::make_shared<Request>();
    }
    static std::shared_ptr<Response> BuildResponseDefault()
    {
        return std::make_shared<Response>();
    }
};


// int main()
// {
//     // Request req(111, 222, '+');
//     //     std::string s;
//     //     req.Serialize(&s);

//     //     std::cout << s << std::endl;
//     std::string s = "{\"oper\":43, \"x\":222, \"y\":111}";
//     Request req;
//     req.Deserialize(s);
//     req.Print();

//     return 0;
// }
